using System;
using System.Collections.Generic;

namespace Runtime.DesignPattern
{
    public abstract class BaseMediator : IMediator
    {
        protected readonly Dictionary<string, IMediatorComponent> _components = new();

        public virtual void Register(IMediatorComponent component)
        {
            if (component == null)
                throw new ArgumentNullException(nameof(component));

            if (string.IsNullOrEmpty(component.ComponentId))
                throw new ArgumentException("Component ID cannot be null or empty", nameof(component));

            if (_components.ContainsKey(component.ComponentId))
                throw new InvalidOperationException($"Component with ID {component.ComponentId} is already registered");

            component.Mediator = this;
            _components.Add(component.ComponentId, component);
        }

        public virtual void Unregister(IMediatorComponent component)
        {
            if (component == null)
                throw new ArgumentNullException(nameof(component));

            if (_components.Remove(component.ComponentId))
            {
                component.Mediator = null;
            }
        }

        public virtual void Send(IMediatorMessage message, IMediatorComponent sender)
        {
            if (message == null)
                throw new ArgumentNullException(nameof(message));

            if (sender == null)
                throw new ArgumentNullException(nameof(sender));

            if (string.IsNullOrEmpty(message.TargetComponentId))
            {
                // 广播消息给所有组件
                BroadcastMessage(message, sender);
            }
            else
            {
                // 发送消息给特定组件
                SendToComponent(message, sender);
            }
        }

        protected virtual void BroadcastMessage(IMediatorMessage message, IMediatorComponent sender)
        {
            foreach (var component in _components.Values)
            {
                if (component != sender)
                {
                    HandleMessage(message, component);
                }
            }
        }

        protected virtual void SendToComponent(IMediatorMessage message, IMediatorComponent sender)
        {
            if (_components.TryGetValue(message.TargetComponentId, out var targetComponent))
            {
                HandleMessage(message, targetComponent);
            }
        }

        protected abstract void HandleMessage(IMediatorMessage message, IMediatorComponent component);
    }
}